package com.example.foo.api.web.account;

import java.math.BigDecimal;
import java.time.Duration;
import java.time.LocalDate;
import java.util.Objects;

import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;

import com.ruoyi.common.core.domain.AjaxResult;
import com.example.foo.account.AccountHelper;
import com.example.foo.account.model.Account;
import com.example.foo.account.service.AccountService;
import com.example.foo.account.service.AccountTransferService;
import com.example.foo.api.boot.TokenHelper;
import com.example.foo.ftt.model.FttUser;
import com.example.foo.ftt.service.FttUserService;
import com.example.support.redis.RedisHelper;

@org.springframework.web.bind.annotation.RestController
public class AccountTransferAction {

	private final AccountService accountService;
	private final AccountTransferService accountTransferService;
	private final FttUserService fttUserService;

	public AccountTransferAction(AccountService accountService,
			AccountTransferService accountTransferService,
			FttUserService fttUserService) {
		this.accountService = accountService;
		this.accountTransferService = accountTransferService;
		this.fttUserService = fttUserService;
	}

	@PostMapping("/api/accounts/transfer")
	public AjaxResult createAccountTransfer(
			@RequestParam("value") BigDecimal value,
			@RequestParam("toUserCellphone") String toUserCellphone,
			@RequestParam("toUserIdname") String toUserIdname) {
		if (value == null) {
			return AjaxResult.error(400, "value must not be null");
		}
		if (StringUtils.isBlank(toUserCellphone)) {
			return AjaxResult.error(400, "toUserCellphone must not be null");
		}
		if (StringUtils.isBlank(toUserIdname)) {
			return AjaxResult.error(400, "toUserIdname must not be null");
		}
		if (value.compareTo(BigDecimal.ZERO) <= 0) {
			return AjaxResult.error(400, "value must not be less than 0");
		}
		Account.Acctc acctc = Account.Acctc.pinmoney;

		Long userId = TokenHelper.verifyToken();

		//
		String lockKey = String.format("lock:transfer:userId_%s", userId);
		if (!RedisHelper.setnxex(lockKey, 15, "-")) {
			return AjaxResult.error(400, "操作频繁，请稍后");
		}

		//
		Integer periodDay = AccountHelper.toPeriodDay(LocalDate.now());
		String ratelimitKey = String.format("ratelimit:transfer:periodDay_%s_userId_%s", periodDay, userId);
		if (RedisHelper.exists(ratelimitKey)) {
			return AjaxResult.error(400, "已达到今日转账次数上限");
		}

		//
		Long fromUserId = userId;
		Long toUserId;
		FttUser fromUserFttUser = fttUserService.findFttUserByUserId(fromUserId);
		if (fromUserFttUser.getState() != FttUser.State.normal) {
			return AjaxResult.error(400, "您的账号已冻结，无法转账。");
		}
		FttUser toUserFttUser = fttUserService.findFttUserByCellphone(toUserCellphone);
		if (toUserFttUser == null) {
			return AjaxResult.error(400, String.format("手机号%s不存在", toUserCellphone));
		}
		toUserId = toUserFttUser.getUserId();
		if (fromUserId.equals(toUserId)) {
			return AjaxResult.error(400, "不能转给自己");
		}
		if (!Objects.equals(toUserFttUser.getIdname(), toUserIdname)) {
			return AjaxResult.error(400, "请输入正确的对方实名姓名");
		}
		if (toUserFttUser.getState() != FttUser.State.normal) {
			return AjaxResult.error(400, "对方的账号已冻结，无法转账。");
		}

		//
		Account account = accountService.findAccountBalance(acctc, userId);
		if (account.getTotal().compareTo(value) < 0) {
			return AjaxResult.error(400, "余额不足");
		}

		//
		String name = "转账-" + fromUserFttUser.getCellphone() + "-" + toUserCellphone;
		accountTransferService.createAccountTransfer(acctc, name, value, fromUserId, toUserId);

		//
		RedisHelper.setex(ratelimitKey, Duration.ofHours(25).getSeconds(), "-");

		return AjaxResult.success();
	}

}
